﻿using System;
using System.Collections.Generic;
using System.Web.UI.WebControls;
using ApplicationGenerator.BusinessModule.Elements;
using ApplicationGenerator.CommonModule;
using ApplicationGenerator.DataAccess;
using ApplicationGenerator.Forms.Actions;
using ApplicationGenerator.Forms.Interfaces;
using ApplicationGenerator.Forms.Utilities;
using ApplicationGenerator.BusinessModule.Interfaces;

namespace ApplicationGenerator.Forms.WebControls
{
    /// <summary>
    /// Kontrolka webowa wyświetlająca elementy formularza
    /// </summary>
    public class FormWebControl : ApplicationGenerator.CommonWeb.BaseControl
    {
        #region Fields
        /// <summary>
        /// Lista przycisków
        /// </summary>
        private List<ButtonControl> _buttonControls;

        /// <summary>
        /// Identyfikator formularza
        /// </summary>
        private Guid _formGuid;
        #endregion

        #region Properties
        /// <summary>
        /// Manager elementów
        /// </summary>
        public ApplicationGenerator.Forms.Utilities.ElementManager Manager
        {
            get;
            private set;
        }

        /// <summary>
        /// Definicja formularza
        /// </summary>
        public FormControlContainer ControlContainer
        {
            get;
            private set;
        }
        #endregion

        #region Constructor
        /// <summary>
        /// Konstruktor
        /// </summary>
        /// <param name="formGuid">Identyfikator formularza</param>
        public FormWebControl(Guid formGuid)
        {
            if (formGuid == Guid.Empty)
            {
                throw new ArgumentException("Wartość nie może być Guid.Empty");
            }

            _formGuid = formGuid;
        }
        #endregion

        #region Methods

        /// <summary>
        /// Wykonuje inicjalizację kontrolki
        /// </summary>
        /// <param name="e">Argumenty</param>
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            try
            {
                InternalInitialize();
                AddWebControls();
                AdditionalInitializeButtons();
            }
            catch (Exception ex)
            {
                AddErrorMessage(ex.Message);
                return;
            }

            InitializeControls();
        }

        /// <summary>
        /// Inicjalizuje ustawienia
        /// </summary>
        private void InternalInitialize()
        {
            try
            {
                ControlContainer = (FormControlContainer)Serializer.Deserialize(Policy.Form, _formGuid);
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("Błąd przy pobieraniu definicji formularza {0}: {1}", _formGuid.ToString(), ex.Message));
            }

            Manager = new ApplicationGenerator.Forms.Utilities.ElementManager(ControlContainer.Source);
            _buttonControls = new List<ButtonControl>();

            BaseControl baseControl = null;
            for (int row = 0; row < ControlContainer.RowsCount; row++)
            {
                for (int column = 0; column < ControlContainer.ColumnsCount; column++)
                {
                    baseControl = ControlContainer.GetControl(row, column);
                    if (baseControl != null)
                    {
                        if (baseControl is BaseMappedControl)
                        {
                            ((BaseMappedControl)baseControl).Source = PathToMetaAdapterConverter.ConvertToMetaAdapter(((BaseMappedControl)baseControl).Path);
                            Manager.RegisterPath(((BaseMappedControl)baseControl).Path);
                        }

                        if (baseControl is ButtonControl)
                        {
                            _buttonControls.Add(baseControl as ButtonControl);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Dodaje kontrolki webowe do kontenera
        /// </summary>
        private void AddWebControls()
        {
            Table table = new Table();
            TableRow tableRow = null;
            TableCell tableCell = null;
            BaseControl baseControl = null;

            for (int row = 0; row < ControlContainer.RowsCount; row++)
            {
                tableRow = new TableRow();
                for (int column = 0; column < ControlContainer.ColumnsCount; column++)
                {
                    tableCell = new TableCell();
                    baseControl = ControlContainer.GetControl(row, column);
                    if (baseControl != null)
                    {
                        if (baseControl is INeedParentIdControl
                            && Page.Request.QueryString[QuerryStringConstants.FormRequestType] == QuerryStringConstants.FormRequestLoaded)
                        {
                            (baseControl as INeedParentIdControl).ParentId = ObtainElementId();
                        }
                        tableCell.Controls.Add(baseControl.Control);
                    }

                    tableRow.Cells.Add(tableCell);
                }

                table.Rows.Add(tableRow);
            }

            this.Controls.Add(table);
        }

        /// <summary>
        /// Inicjalizuje kontrolki webowe
        /// </summary>
        private void InitializeControls()
        {
            string requestType = Page.Request.QueryString[QuerryStringConstants.FormRequestType];
            if (string.IsNullOrEmpty(requestType))
            {
                AddErrorMessage("Należy podać typ żądania dla wyświetlanego formularza");
                return;
            }

            InitializeWebControls();
            if (requestType == QuerryStringConstants.FormRequestLoaded)
            {
                LoadWebControls();
            }
        }

        /// <summary>
        /// Inicjalizuje kontrolki webowe
        /// </summary>
        private void InitializeWebControls()
        {
            BaseControl baseControl = null;
            for (int row = 0; row < ControlContainer.RowsCount; row++)
            {
                for (int column = 0; column < ControlContainer.ColumnsCount; column++)
                {
                    baseControl = ControlContainer.GetControl(row, column);
                    if (baseControl is IInitializeControl)
                    {
                        ((IInitializeControl)baseControl).Initialize();
                    }
                }
            }
        }

        /// <summary>
        /// Zaczytuje wartości kontrolek na podstawie modelu
        /// </summary>
        private void LoadWebControls()
        {
            Manager.LoadElement(ObtainElementId());
            BaseControl baseControl = null;
            for (int row = 0; row < ControlContainer.RowsCount; row++)
            {
                for (int column = 0; column < ControlContainer.ColumnsCount; column++)
                {
                    baseControl = ControlContainer.GetControl(row, column);
                    if (baseControl is ILoadControl && baseControl is BaseMappedControl)
                    {
                        IModel element = Manager.GetElement(((BaseMappedControl)baseControl).Path);
                        ((ILoadControl)baseControl).Load(element);
                    }
                }
            }
        }

        /// <summary>
        /// Przeprowadza dodatkową inicjalizację kontrolek - przycisków
        /// </summary>
        private void AdditionalInitializeButtons()
        {
            foreach (ButtonControl buttonControl in _buttonControls)
            {
                ((Button)buttonControl.Control).Click += new EventHandler(FormWebControl_Click);
            }
        }

        /// <summary>
        /// Handler kliknięcia przycisku
        /// </summary>
        /// <param name="sender">Kliknięty przycisk</param>
        /// <param name="e">Argumenty</param>
        private void FormWebControl_Click(object sender, EventArgs e)
        {
            //obsługa jakichś walidacji, jeśli akcja jest typu zapis, dalej, lub też uruchom przepływ
            foreach (ButtonControl buttonControl in _buttonControls)
            {
                if (buttonControl.Control == (WebControl)sender)
                {
                    buttonControl.ExecuteAction(this);
                }
            }
        }

        /// <summary>
        /// Pobiera id zaczytanego elementu
        /// </summary>
        /// <returns>Id zaczytanego elementu</returns>
        public int ObtainElementId()
        {
            string elementId = this.Page.Request.QueryString[QuerryStringConstants.ElementId];
            int convertedElementId;
            if (!int.TryParse(elementId, out convertedElementId))
            {
                throw new Exception("Należy podać id elementu. Podano: " + elementId);
            }

            return convertedElementId;
        }

        #endregion
    }

}
